package SQL.plan;
import heap.ResultField;
import heap.ResultSchema;
import SQL.scan.*;


/**
 * A query tree constructed for the purpose of cost comparison is called a plan.
 * it accesses the database's metadata, but not the actual data
 * allow the plan to calculate the values B(s), R(s), and V(s, F) for its query
 * @author Azure
 *
 */
public class Plan {

    public Scan open(){
    	return scan;
    }
    
    public void close()throws Exception{
    	scan.close();
    }
    
//format..
	public ResultSchema getSchema(String sql) throws Exception {
		ResultSchema schema = scan.getSchema();
		ResultSchema result = new ResultSchema();
		// 0 init
		// 1 select done
		// 2 to none space
		// 3
		
		int state = 0;
		int x = 0;
		int count = 0;
//		int bra = 0;
		while (state < 10) {
			if (state == 0) {
				x = sql.toLowerCase().indexOf("select");
				state = 1;
			}
			else if (state == 1) {
				x = x + 6;
				state = 2;
			}
			else if (state == 2) {
				try {
				while (sql.charAt(x) == ' ')
					x++;
				} catch (Exception e) {
					break;
				}
				state = 3;
			}
			else if (state == 3) {
				if (sql.charAt(x) == '*') {
					for (int i = 0; i < schema.size(); i++) {
						String name = schema.get(i).name;
						if (name.contains(".")) {
							name = name.split("\\.")[1];
						}
						result.add(new ResultField(name, schema.get(count++).type));
					}
					return result;
				} else if (sql.toLowerCase().indexOf("distinct") == x) {
						x += 8;
						state = 2;
				} else if (sql.length() == x || sql.toLowerCase().indexOf("from") == x ||
						sql.toLowerCase().indexOf("where", x) == x ||
						sql.toLowerCase().indexOf("order", x) == x ||
						sql.toLowerCase().indexOf("group", x) == x ||
						sql.toLowerCase().indexOf("having", x) == x ||
						sql.toLowerCase().indexOf(";",x ) == x) {
					x += 8;
					state = 110;
				} else {
					StringBuffer buffer = new StringBuffer();
					int bra = 0;
					while (sql.length() > x && ( bra != 0 || sql.charAt(x) != ',')) {
						if (bra == 0 &&( sql.length() == x || 
								sql.toLowerCase().indexOf("from", x) == x ||
								sql.toLowerCase().indexOf("where", x) == x ||
								sql.toLowerCase().indexOf("order", x) == x ||
								sql.toLowerCase().indexOf("group", x) == x ||
								sql.toLowerCase().indexOf("having", x) == x ||
								sql.toLowerCase().indexOf(";", x) == x)) {
							x += 8;
							state = 110;
							break;
						}
						buffer.append(sql.charAt(x));
						if (sql.charAt(x) == '(')
							bra++;
						if (sql.charAt(x) == ')')
							bra--;
						x++;
					}
					if (sql.length() < x) {
						state = 110;
					}
					x++;
					if (state != 110)
						state = 2;
					String name = buffer.toString();
					if (name.charAt(0) <= 'Z' && name.charAt(0) >= 'A' ||
							name.charAt(0) <= 'z' && name.charAt(0) >= 'a' ||
							name.charAt(0) == '_') {
						if (name.contains(".")) {
							name = name.split("\\.")[1];
						}
					}
					name = name.trim();
					//System.out.println(name);
					result.add(new ResultField(name, schema.get(count++).type));
				}
			}
		}
		
		return result;
	}
    
    public int blocksAccessed(){//calculate B(s)
    	return 0;
    }
    public int recordsOutput(){//calculate R(s)
    	return 0;
    }
    public int distinctValues(String fldname){//calculate V(s,F)
    	return 0;
    }


    Scan scan;
    
}
